package com.sduept.nwld.fault.outer.manager;


import com.sduept.bigdata.fault.common.ParamDesc;
import com.sduept.bigdata.fault.entity.FaultRecord;
import com.sduept.cim.model.extend.LineSegment;
import com.sduept.cim.model.wires.ACLineSegment;
import com.sduept.cim.model.wires.DcLinesegment;
import com.sduept.core.ParamManager;
import com.sduept.core.dao.SuperDAO;
import com.sduept.core.entity.SystemParameter;
import com.sduept.nwld.dataserver.manager.cim.CimManager;
import com.sduept.nwld.fault.outer.model.FaultTripInfo;
import com.sduept.nwld.fault.outer.model.FaultTripInfoLog;
import com.sduept.nwld.fault.outer.model.factory.AbstractOuterFaultModelFactory;
import com.sduept.nwld.fault.outer.model.factory.AclineOuterFaultModelFactory;
import com.sduept.nwld.fault.outer.model.factory.DclineOuterFaultModelFactory;
import com.sduept.nwld.fault.outer.model.factory.StationDeviceOuterFaultModelFactory;
import com.sduept.utils.DateUtil;
import com.sduept.utils.MD5;
import com.sduept.utils.PojoJsonXmlUtil;
import com.sduept.utils.WebRequestUtil;
import com.thoughtworks.xstream.core.util.Base64Encoder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.xml.bind.JAXBException;
import java.io.IOException;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class FaultToOMSServerManager {
	
	@Autowired
	private CimManager cm;
	@Autowired
	private SuperDAO   dao;
	@Autowired
    private ParamManager cache;
	private static final Object sendLock = new Object();

	/**
	 * 发送故障跳闸信息到OMS平台
	 * @param fr
	 * @param currentOption
	 *  0:新增/更新
	 *  1：删除
	 */
	/**
	 * @param fr
	 * @param currentOption
	 */
	public void sendFaultToOmsServer(FaultRecord fr,int currentOption){
		boolean checkResult = checkIsNeededPushToOms(fr);
		if(checkResult){//具备推送条件
			String str = getFaultTripInfoXml(fr,currentOption);//获取跳闸信息XML形式的字符串
			if(StringUtils.isEmpty(str)){
				log.error("故障生成XML文件有误"+fr.getId()+"--"+fr.getEquipment_id()+"--"+fr.getFaultTime());
				return;
			}
			String url = cache.get(ParamDesc.OMS_SERVICE_URL).getValue();
			String soap = cache.get(ParamDesc.OMS_SERVICE_SOAP).getValue();
			String returnCode = null;
			String currentCheckCode = MD5.md5(str);
			boolean needSend = false;
			synchronized (sendLock) {
				List<FaultTripInfoLog> list =  dao.findByCondition("faultId=?", new Object[]{fr.getId()},"order by createDate DESC", null, FaultTripInfoLog.class);//(FaultTripInfoLog.class, "faultId=? AND checkCode=? AND status=0", fr.getId(),currentCheckCode);
				FaultTripInfoLog log = null;
				if(list.size()>0){
					log = list.get(0);
					if(StringUtils.isEmpty(log.getResult())){
						needSend=true;
					}else if(!currentCheckCode.equals(log.getCheckCode())){
						needSend=true;
					}
				}else{
					needSend=true;
				}
				if(needSend){
					soap = soap.replace("?", base64Encode(str));
					try {
						String omsReturn = WebRequestUtil.invokeWebServiceBySoap(url, soap, null);
						if(StringUtils.isNotEmpty(omsReturn)){
							Document doc = Jsoup.parse(omsReturn);
							Elements eles = doc.getElementsByTag("replyCode");
							for(Element e:eles){
								returnCode = e.text();
								break;
							}
						}
					} catch (IOException e) {
						this.log.error("到OMS服务器异常");
						//e.printStackTrace();
					}
					if(log==null || !log.getCheckCode().equals(currentCheckCode)){
						log = new FaultTripInfoLog();
						log.setContent(str);
						log.setCheckCode(currentCheckCode);
						log.setFaultId(fr.getId());
						log.setCreateDate(new Date());
						log.setResult(returnCode);
					}else {
						log.setResult(returnCode);
					}
					dao.createOrUpdate(log,FaultTripInfoLog.class);
				}
			}
		}
	}
	/**
	 * @return
	 */
	private boolean checkIsNeededPushToOms(FaultRecord fr){
		//1、检测OMS 推送服务是否开启
		SystemParameter sp = cache.get(ParamDesc.OMS_SERVICE_PUSH_SWITCH);//获取OMS服务推送开关参数，0：表示可以推送，1：表示不推送
		if(sp==null || StringUtils.isEmpty(sp.getValue()) || Integer.parseInt(sp.getValue())==1){
			return false;
		}
		//2、检测本次故障是否需要推送
		if(fr.getSendToOms()==null || !fr.getSendToOms()){
			return false;
		}
		//3、检测设备类型是否在推送范围内
		SystemParameter omsPushTypes = cache.get(ParamDesc.OMS_SERVICE_PUSH_ETYPES);
		if(omsPushTypes==null || StringUtils.isEmpty(omsPushTypes.getValue())||!omsPushTypes.getValue().contains(fr.getEtype())){
			return false;
		}else if("线路".equals(fr.getEtype()) && StringUtils.isNotEmpty(fr.getEquipment_id())){
			//TODO 设备类型如果是线路且故障设备是直流设备不予推送，以后可能会完善
			LineSegment line = cm.getLineSegmentById(fr.getEquipment_id());
			if(line instanceof DcLinesegment){
				return false;
			}
		}
		//4、检测推送日期是否在有效范围内
		SystemParameter omsPushEffectiveInterval = cache.get(ParamDesc.OMS_SERVICE_PUSH_EFFECTIVE_INTERVAL);
		if(omsPushEffectiveInterval!=null && StringUtils.isNotEmpty(omsPushEffectiveInterval.getValue())
				&& Integer.parseInt(omsPushEffectiveInterval.getValue())>0){
			Date currentTime = new Date();
			long currentTimeMs = currentTime.getTime();
			long faultTimeMs = fr.getFaultTime().getTime();
			if(Math.abs(currentTimeMs-faultTimeMs)>Integer.parseInt(omsPushEffectiveInterval.getValue())){
				//如果配置了推送失效间隔时间，且当前时间与故障时间间隔大于推送失效间隔，直接返回不推送
				log.error("当前故障填报时间："+DateUtil.getStringDate(currentTime, DateUtil.pattern_ymdhms)+"，"
						+ "故障实际时间："+DateUtil.getStringDate(fr.getFaultTime(), DateUtil.pattern_ymdhms)+"，超出了推送有效间隔");
				return false;
			}
		}
		//5、检测URL 是否配置
		SystemParameter urlparam = cache.get(ParamDesc.OMS_SERVICE_URL);
		if(urlparam==null || StringUtils.isEmpty(urlparam.getValue())){
			return false;
		}
		//6、检测soap是否配置
		SystemParameter soapParam = cache.get(ParamDesc.OMS_SERVICE_SOAP);
		if(soapParam==null || StringUtils.isEmpty(soapParam.getValue())){
			return false;
		}
		return true;
	}
	/**
	 * 构建故障跳闸信息
	 * @param model
	 * @param etype
	 * @return
	 */
	private FaultTripInfo getFaultTripInfo(FaultRecord fr,int currentOption){
		AbstractOuterFaultModelFactory factory = null;
		FaultTripInfo result = null;
		try {
			if("线路".equals(fr.getEtype())){
				LineSegment line = cm.getLineSegmentById(fr.getEquipment_id());
				if(line instanceof ACLineSegment){
					factory = AclineOuterFaultModelFactory.getInstance();
				}else if(line instanceof DcLinesegment){
					factory = DclineOuterFaultModelFactory.getInstance();
				}
			}else{
				factory = StationDeviceOuterFaultModelFactory.getInstance();
			}
			result = factory.getFaultTripInfo(fr);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
	}
	/**
	 * 构建故障跳闸信息xml字符串形式
	 * @param model
	 * @param etype
	 * @return
	 */
	private String getFaultTripInfoXml(FaultRecord fr,int currentOption){
		FaultTripInfo info = null;
		if(currentOption==1 || fr.getStatus()==1){
			info = new FaultTripInfo();
			//如果当前的操作是1（删除操作）将故障设置为1 非故障
			info.setStatus(1);
			info.setId(fr.getId());
		}else{
			info = getFaultTripInfo(fr,currentOption);
		}
		try {
			if(info!=null){
				String xml =  PojoJsonXmlUtil.beanToXml(info, FaultTripInfo.class);
				//log.info(xml);
				return xml;
			}
		} catch (JAXBException e) {
			e.printStackTrace();
		}
		return "";
	}
	
	/**
	 * base64 编码
	 * @param s
	 * @return
	 */
	private String base64Encode(String s){
		Base64Encoder en = new Base64Encoder();
		return en.encode(s.getBytes());
	}
	/**
	 * base64解码
	 * @param s
	 * @return
	 */
	private String base64Decode(String s){
		Base64Encoder en = new Base64Encoder();
		return new String(en.decode(s));
	}
}

